<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
<div id="test">

</div>
<script>
    //模拟翻译。
    var i18n = {
        prop: function (key) {
            return "language:" + key
        }
    };


    function _trim(str){
        return str.replace(/^\s*|\s*$/g,'');
    }
    function render(temp, data){
        var mathReg = /{{([^}]+)}}/g;
        var idx = 0, dList = [], rs;

        //用replace 方法来生成返回数据和埋点
        rs = temp.replace(mathReg, function (match) {
            var cont = match.substring(2, match.length - 2);
            //trim下
            cont = _trim(cont);
            if (cont.indexOf('(') == -1&&cont.indexOf('?')==-1) {
                //不是方法
                //比如 name 返回  data.name||name 这样就可以在自身属性上取值或是从外部取值
                //当上方的设置会忽略掉自身属性为false的值
                //添加{{cont}} 只是用于标记找不到的key，这样可以在模板中比较方便的定位
                cont = '(typeof d.' + cont+' ==="undefined"?"{{'+cont+'}}":d.'+cont+')';
            }
            dList.push(cont);
            return '${' + (idx++) + '}'
        });

        //字符串数据转换为方法来执行。
        var list = (new Function('d', 'return [' + dList.join(',') + ']'))(data);
        //通过埋点来重新装载数据
        rs = rs.replace(/\${\d+}/g, function (match) {
            idx = match.substring(2, match.length - 1);
            return list[idx];
        });
        return rs;
    }

    var userInfo = {name: "will"};
    var temp = 'test:{{i18n.prop("text.label.Apply.for.account")}}-----{{name}}|||{{fff}} !!!!!{{d.name?"有name值":"没有name值"}}';
    //test
    var rs = render(temp, userInfo);
    // test:language:text.label.Apply.for.account-----will|||{{fff}}

    console.log(rs);

</script>
</body>
</html>